package com.hboxs.asl.controller.app.member;

import com.hboxs.asl.Constant;
import com.hboxs.asl.JsonMessage;
import com.hboxs.asl.Page;
import com.hboxs.asl.Pageable;
import com.hboxs.asl.controller.app.BaseController;
import com.hboxs.asl.entity.*;
import com.hboxs.asl.service.*;
import org.apache.commons.lang.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.*;

/**
 * Created by xxx on 2016/11/25.
 * Controller - 订单
 */
@Controller(value = "appMemberOrderController")
@RequestMapping(value = "/app/m/order")
public class OrderControl extends BaseController {

    //新订单计数，通知后台
    public static int count = 0;

    @Resource(name = "memberServiceImpl")
    private MemberService memberService;
    @Resource(name = "orderServiceImpl")
    private OrderService orderService;
    @Resource(name = "cartServiceImpl")
    private CartService cartService;
    @Resource(name = "receiverServiceImpl")
    private ReceiverService receiverService;
    @Resource(name = "paymentMethodServiceImpl")
    private PaymentMethodService paymentMethodService;
    @Resource(name = "shippingMethodServiceImpl")
    private ShippingMethodService shippingMethodService;
    @Resource(name = "couponCodeServiceImpl")
    private CouponCodeService couponCodeService;
    @Resource(name = "shippingServiceImpl")
    private ShippingService shippingService;


    /**
     * 虚拟订单页面
     *
     * @param payPointJson {merchant1:paypoint1,merchant2:paypoint2}
     */
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public
    @ResponseBody
    Object info(String code, String payPointJson , Boolean isEncode) {


        try {
            if (isEncode!=null && isEncode == true && payPointJson != null) {
                payPointJson = java.net.URLDecoder.decode(payPointJson, "utf-8");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return JsonMessage.error("数据错误");
        }


        Map<Long, BigDecimal> order2Point = changeJsonToOrderPoint(payPointJson);

        Member member = memberService.getCurrentByToken();
        if (member == null) {
            return JsonMessage.USER_NOT_LOGIN;
        }
        Cart cart = cartService.getCurrentByToken();
        if (cart == null || cart.isEmpty()) {
            return JsonMessage.error("购物车不存在");
        }
        if (!isValid(cart)) {
            return JsonMessage.error("购物车参数非法");
        }
        Receiver receiver = receiverService.findDefault(memberService.getCurrentByToken());

        List<Order> orders = orderService.build(
                cart, null, null, couponCodeService.findByCode(code), false,
                null, false, new BigDecimal(0), null
        );

        // 自营订单
        Order adminOrder = orderService.build(
               cart, null, null, shippingMethodService.findDefault(), couponCodeService.findByCode(code), false,
                null, false, new BigDecimal(0), null
        );

        if (adminOrder != null) orders.add(adminOrder);

        // 判断当前会员在确认订单上可以使用的积分,1积分当1元使用
        BigDecimal orderTurnToPoint = new BigDecimal(0);
        for (Order order : orders) {
            orderTurnToPoint = orderTurnToPoint.add(order.getAmountPayable().multiply(Constant.POINT_SCALE));
        }

        BigDecimal maxUsablePoint = member.getPoint().compareTo(orderTurnToPoint) <= 0 ? member.getPoint() : orderTurnToPoint;

        // 支付积分不能大于订单金额和用户积分的最小值
        BigDecimal payPoint = new BigDecimal(0);

        if (order2Point != null) {
            for (Long key : order2Point.keySet()) {
                BigDecimal value = order2Point.get(key);
                payPoint = payPoint.add(value);
            }
            if (payPoint.compareTo(maxUsablePoint) > 0) {
                return JsonMessage.error("积分无效");
            }
        }

        if (order2Point != null) {
            List<Merchant> merchants = cart.getMerchants();
            Long merchantId = null;
            for (Order order : orders){
                merchantId = order.getMerchant().getId();
                order.setPayPoint(order2Point.get(merchantId) == null ? new BigDecimal(0) : order2Point.get(merchantId));
            }
            if (payPoint != null && adminOrder != null) {
                adminOrder.setPayPoint(order2Point.get(0l));
            }

        }

        // 用非促销购物车项选择优惠卷,按找减价排序,
        BigDecimal couponPrice = cart.getPrice();
        List<CouponCode> couponCodes = couponCodeService.findListByPrice(member, true, false, false, couponPrice);

        return JsonMessage.success(
                "order", JsonMessage.optimiseObj(
                        orders,
                        "orderItems.product.id#product.name#product.image#product.unit#product.price#product.promotionPrice#product.specValNames#quantity#subtotal#weight",
                        "freight", "amountPayable", "weight", "quantity", "merchant.name", "merchant.logo", "merchant.id", "point", "mPoint", "payPoint"
                )
                , "receiver", receiver

                , "maxUsablePoint", maxUsablePoint

                , "cartToken", cart.getToken()

                , "couponCodes", JsonMessage.optimiseObj(

                        couponCodes, "code", "coupon.id", "coupon.name", "coupon.cut", "coupon.maximumPrice"

                )
        );

    }



    /**
     * 创建订单
     *
     * @param payPointJson 积分{merchant1:paypoint1,merchant2:paypoint2}
     * @param cartToken    购物车
     * @param receiverId   收货地址
     * @param isInvoice    是否开据发票
     * @param code         优惠码
     * @param memoJson     备注{merchant1:memo1,merchant2:memo2}
     * @return json
     */
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    public
    @ResponseBody
    Object create(String payPointJson, String cartToken, Long receiverId, @RequestParam(defaultValue = "false") Boolean isInvoice,
                  String code, String invoiceTitle, String memoJson, Boolean isEncode) {
        synchronized (String.valueOf(memberService.getCurrentByToken()).intern()) {

            try {
                if (isEncode != null && isEncode == true && payPointJson != null) {
                    payPointJson = java.net.URLDecoder.decode(payPointJson, "utf-8");
                }
                if (isEncode != null && isEncode == true && memoJson != null) {
                    memoJson = java.net.URLDecoder.decode(memoJson, "utf-8");
                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            Map<Long, BigDecimal> order2Point = changeJsonToOrderPoint(payPointJson);
            Map<Long, String> merchant2memo = changeJsonToMemo(memoJson);

            Cart cart = cartService.getCurrentByToken();
            if (cart == null || cart.isEmpty()) {
                return JsonMessage.error("购物车不能为空");
            }
            if (!StringUtils.equals(cart.getToken(), cartToken)) {
                return JsonMessage.error("购物车商品已修改，请检查购物车");
            }
            if (cart.getIsLowStock()) {
                return JsonMessage.error("购物车商品库存不足，请修改购物车商品");
            }
            Receiver receiver = receiverService.find(receiverId);
            if (receiver == null) {
                return JsonMessage.error("收货地址不存在");
            }

            // 默认一个微信支付
            List<PaymentMethod> paymentMethods = paymentMethodService.findList(1, null, null);
            if (paymentMethods == null || paymentMethods.size() == 0) {
                return JsonMessage.error("支付方式不存在");
            }
            PaymentMethod paymentMethod = paymentMethods.get(0);
            ShippingMethod shippingMethod = shippingMethodService.findDefault();
            if (shippingMethod == null) {
                return JsonMessage.error("配送方式不存在");
            }

            //检查用户积分是否够用
            BigDecimal payPoint = new BigDecimal(0);
            if (order2Point != null) {
                for (Long key : order2Point.keySet()) {
                    BigDecimal value = order2Point.get(key);
                    payPoint = payPoint.add(value);
                }
                if (payPoint.compareTo(memberService.getCurrentByToken().getPoint()) > 0) {
                    return JsonMessage.error("积分无效");
                }
            }

            CouponCode couponCode = couponCodeService.findByCode(code);

            List<Order> orders = orderService.create(cart, receiver, paymentMethod, shippingMethodService.findDefault(), couponCode,
                    isInvoice, invoiceTitle, false, new BigDecimal(0), merchant2memo, null);

            if (order2Point != null) {
                List<Merchant> merchants = cart.getMerchants();
                Long merchantId = null;
                for (Order order : orders) {
                    if (order.getMerchant() == null) {
                        order.setPayPoint(order2Point.get(0l) == null ? new BigDecimal(0) : order2Point.get(0l));
                    } else {
                        merchantId = order.getMerchant().getId();
                        order.setPayPoint(order2Point.get(merchantId) == null ? new BigDecimal(0) : order2Point.get(merchantId));
                    }
                    orderService.update(order);
                }
            }

            count++;

            return JsonMessage.success(

                    "receiver", JsonMessage.optimiseObj(receiver, "zipCode", "phone", "address", "areaName", "consignee")

                    , "order", JsonMessage.optimiseObj(orders, "sn", "freight", "amountPayable")
            );
        }
    }

    /**
     * 我的订单
     *
     * @param status 状态代码:0待支付;1待发货;2退换货（未收货，包含已申请和未申请退换货的订单）;3已完成(待评论) ;4全部訂單;5.待收货（全部为未申请退换货）
     * @return json
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public
    @ResponseBody
    Object list(Pageable pageable, int status) {

        try {
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }

            Page page = orderService.findPage(member, pageable, status);

            return JsonMessage.success(

                    "totalPage", page.getTotalPages()

                    , "pageNumber", page.getPageNumber()

                    , "pageSize", page.getPageSize()

                    , "total", page.getTotal()

                    , "content", JsonMessage.optimiseObj(

                            page.getContent(),

                            "sn", "amount", "paymentStatusOrdinal", "orderStatusOrdinal", "shippingStatusOrdinal", "displayStatus", "returnStatus","isExpired",

                            "freight", "orderItems.product.image#product.name#product.specValNames#product.id#quantity#subtotal#price#id#hasReview#hasApplyReturn"
                    )

            );

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return JsonMessage.UNKNOWN_ERROR;
    }

    /**
     * 订单详情
     *
     * @param sn 订单号
     * @return json
     */
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    public
    @ResponseBody
    JsonMessage detail(String sn) {
        try {
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            Order order = orderService.findBySn(sn);
            if (order == null) {
                return JsonMessage.error("订单不存在");
            }
            if (!member.getOrders().contains(order)) {
                return JsonMessage.error("订单不属于该会员");
            }

            //查找运单号
            String url = shippingService.queryByOrder(order);

            return JsonMessage.success(

                    "order", JsonMessage.optimiseObj(

                            order,

                            "orderItems.product.id#product.name#product.image#product.price#product.promotionPrice#product.specValNames#quantity#subtotal#hasReview#id#hasApplyReturn#weight" +
                                    "#returnsStatusValue"

                            , "orderStatusOrdinal", "paymentStatusOrdinal", "shippingStatusOrdinal"

                            , "displayStatus"

                            , "consignee", "phone", "areaName", "address"

                            , "sn", "amount", "weight", "quantity", "shippingMethodName", "freight"

                            , "couponCode.coupon.name", "payPoint", "memo", "isExpired"

                    ),

                    "shippingUrl", url
            );

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return JsonMessage.UNKNOWN_ERROR;
    }

    /**
     * 确认收货完成订单
     *
     * @param sn 订单号
     * @return json
     */
    @RequestMapping(value = "/complete", method = RequestMethod.POST)
    public
    @ResponseBody
    Object complete(String sn) {

        try {
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            Order order = orderService.findBySn(sn);
            if (order == null) {
                return JsonMessage.error("订单不存在");
            }
            if (!member.getOrders().contains(order)) {
                return JsonMessage.error("订单不属于该会员");
            }
            if (order.isExpired()) {
                return JsonMessage.error("订单已过期");
            }
            if (Order.OrderStatus.confirmed.equals(order.getOrderStatus()) && Order.ShippingStatus.shipped.equals(order.getShippingStatus())) {
                orderService.complete(order, null);
            }
            return JsonMessage.success();

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return JsonMessage.UNKNOWN_ERROR;
    }

    /**
     * 取消订单
     *
     * @param sn 订单号
     * @return json
     */
    @RequestMapping(value = "/cancel", method = RequestMethod.POST)
    public
    @ResponseBody
    Object cancel(String sn) {

        try {
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            Order order = orderService.findBySn(sn);
            if (order == null) {
                return JsonMessage.error("订单不存在");
            }
            if (!member.getOrders().contains(order)) {
                return JsonMessage.error("订单不属于该会员");
            }
            if (order.isExpired()) {
                return JsonMessage.error("订单已过期");
            }
            if (!Order.OrderStatus.confirmed.equals(order.getOrderStatus()) || !Order.PaymentStatus.unpaid.equals(order.getPaymentStatus())) {
                return JsonMessage.error("订单已支付,不能取消");
            }
            if (order.isLocked(null)) {
                return JsonMessage.error("该订单已被锁定，请稍后再试");
            }
            orderService.cancel(order, null);
            return JsonMessage.success();

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return JsonMessage.UNKNOWN_ERROR;
    }

    /**
     * 登陆路后台订单计数清零
     *
     * @return json
     */
    @RequestMapping(value = "/clear", method = RequestMethod.GET)
    public
    @ResponseBody
    Object clear() {
        count = 0;
        return JsonMessage.success(count);
    }

    /**
     * 后台轮询
     */
    @RequestMapping(value = "/query", method = RequestMethod.GET)
    public
    @ResponseBody
    Object query() {
        int c = count;
        count = 0;
        return JsonMessage.success(c);
    }

    /**
     * 格式化 分离订单积分 {merchant1:paypoint1,merchant2:paypoint2}
     *
     * @param payPointJson
     * @return
     */
    public static Map<Long, BigDecimal> changeJsonToOrderPoint(String payPointJson) {
        if (payPointJson == null) {
            return null;
        }
        JSONObject payPointJsonObject = new JSONObject(payPointJson);
        Map<Long, BigDecimal> order2Point = new HashMap<>();
        Set<String> ks = payPointJsonObject.keySet();
        for (String k : ks) {
            order2Point.put(Long.valueOf(k), BigDecimal.valueOf(payPointJsonObject.getDouble(k)));
        }
        return order2Point;
    }


    /**
     * 格式化 分离订单备注 {merchant1:memo1,merchant2:memo2}
     *
     * @param memoJson
     * @return
     */
    public static Map<Long, String> changeJsonToMemo(String memoJson) {
        if (memoJson == null) {
            return null;
        }
        JSONObject memoJsonObject = new JSONObject(memoJson);
        Map<Long, String> order2Point = new HashMap<>();
        Set<String> ks = memoJsonObject.keySet();
        for (String k : ks) {
            order2Point.put(Long.valueOf(k), memoJsonObject.getString(k));
        }
        return order2Point;
    }

    /**
     * 格式化 分离订单sn ["sn1","sn2","sn3"]
     *
     * @param snsJson
     * @return
     */
    public static List<String> changeJsonToSns(String snsJson) {
        System.out.println("snsJson:" + snsJson);
        if (snsJson == null) {
            return null;
        }

        JSONArray snsJsonArray = new JSONArray(snsJson);
        List<String> sns = new ArrayList<>();

        for (int i = 0; i < snsJsonArray.length(); i++) {
            String sn = snsJsonArray.getString(i);
            if (!StringUtils.isEmpty(sn)) {
                sns.add(sn);
            }
        }

        return sns;
    }

    /**
     * 请求快递url
     */
    @RequestMapping(value = "/shipping_url",method = RequestMethod.POST)
    public
    @ResponseBody
    Object getShippingUrl(String sn){
        Order order = orderService.findBySn(sn);
        if (order == null) {
            return JsonMessage.error("订单不存在");
        }
        String url = shippingService.queryByOrder(order);
        return JsonMessage.success(url);
    }

}
